package com.umeox.moto.common.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import com.umeox.moto.common.log.LogUtils;
import com.umeox.moto.common.log.Logger;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;

public class NetUtils {
    public static final String NETWORK_TYPE_WIFI = "wifi";
    public static final String NETWORK_TYPE_4G = "4g";
    public static final String NETWORK_TYPE_3G = "3g";
    public static final String NETWORK_TYPE_2G = "2g";
    public static final String NETWORK_TYPE_WAP = "wap";
    public static final String NETWORK_TYPE_UNKNOWN = "unknown";
    public static final String NETWORK_TYPE_DISCONNECT = "disconnect";

    public static boolean hasSimCard() {
        final TelephonyManager tm = (TelephonyManager) AppUtils.getApp().getSystemService(Service.TELEPHONY_SERVICE);
        int state = tm.getSimState();
        Log.i("TelephonyManager", "hasSimCard: " + state);
        @SuppressLint("HardwareIds") final String simSerialNumber = tm.getSimSerialNumber();

        Log.i("TelephonyManager",
                "SN: " + simSerialNumber
                        + " phoneType " + tm.getPhoneType()
                        + " Name:" + tm.getSimOperatorName()
                        + " isEmpty:" + TextUtils.isEmpty(tm.getSimOperatorName())

        );
        return state == TelephonyManager.SIM_STATE_READY;
    }

    /**
     * SIM卡运营商是否可用
     *
     * @return
     */
    public static boolean simOperatorUnavailable() {
        final TelephonyManager tm = (TelephonyManager) AppUtils.getApp().getSystemService(Service.TELEPHONY_SERVICE);
        final String operatorName = tm.getSimOperatorName();
        return TextUtils.isEmpty(operatorName);

    }

    public static int getNetworkType() {
        ConnectivityManager connectivityManager = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager == null ? null : connectivityManager.getActiveNetworkInfo();
        return networkInfo == null ? -1 : networkInfo.getType();
    }

    public static String getNetworkTypeName() {
        TelephonyManager telephonyManager = (TelephonyManager) AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE);
        ConnectivityManager cm = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (telephonyManager == null || cm == null) {
            return NETWORK_TYPE_UNKNOWN;
        }
        if (cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) {
            return "WIFI";
        } else {
            @SuppressLint("MissingPermission")
            int type = telephonyManager.getNetworkType();
            switch (type) {
                case TelephonyManager.NETWORK_TYPE_GPRS:
                    return "GPRS";
                case TelephonyManager.NETWORK_TYPE_EDGE:
                    return "EDGE";
                case TelephonyManager.NETWORK_TYPE_UMTS:
                    return "UMTS";
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                    return "HSDPA";
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                    return "HSUPA";
                case TelephonyManager.NETWORK_TYPE_HSPA:
                    return "HSPA";
                case TelephonyManager.NETWORK_TYPE_CDMA:
                    return "CDMA";
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    return "CDMA - EvDo rev. 0";
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    return "CDMA - EvDo rev. A";
                case TelephonyManager.NETWORK_TYPE_EVDO_B:
                    return "CDMA - EvDo rev. B";
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                    return "CDMA - 1xRTT";
                case TelephonyManager.NETWORK_TYPE_LTE:
                    return "LTE";
                case TelephonyManager.NETWORK_TYPE_EHRPD:
                    return "CDMA - eHRPD";
                case TelephonyManager.NETWORK_TYPE_IDEN:
                    return "iDEN";
                case TelephonyManager.NETWORK_TYPE_HSPAP:
                    return "HSPA+";
                case 16:
                    return "GSM";
                case 17:
                    return "TD_SCDMA";
                case 18:
                    return "IWLAN";
                case 19:
                    return "LTE_CA";
                default:
                    return "UNKNOWN";
            }
        }
    }

    public static String getActiveNetworkTypeName() {
        ConnectivityManager manager = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo;
        String type = NETWORK_TYPE_DISCONNECT;
        if (manager == null || (networkInfo = manager.getActiveNetworkInfo()) == null) {
            return type;
        }

        if (networkInfo.isConnected()) {
            String typeName = networkInfo.getTypeName();
            if ("WIFI".equalsIgnoreCase(typeName)) {
                type = NETWORK_TYPE_WIFI;
            } else if ("MOBILE".equalsIgnoreCase(typeName)) {
                //String proxyHost = android.net.Proxy.getDefaultHost();//deprecated
                String proxyHost = System.getProperty("http.proxyHost");
                type = TextUtils.isEmpty(proxyHost) ? getNetworkClass() : NETWORK_TYPE_WAP;
            } else {
                type = NETWORK_TYPE_UNKNOWN;
            }
        }
        return type;
    }

    public static boolean isConnected() {
        ConnectivityManager cm = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnected()) {
            if (info.getState() == NetworkInfo.State.CONNECTED) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断当前网络是否可用(6.0以上版本)
     * 实时
     * @return
     */
    public static boolean isNetSystemUsable() {
        boolean isNetUsable = false;
        ConnectivityManager manager = (ConnectivityManager)
                AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            NetworkCapabilities networkCapabilities =
                    manager.getNetworkCapabilities(manager.getActiveNetwork());
            if (networkCapabilities != null) {
                isNetUsable = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
            }
        }
        return isNetUsable;
    }

    public static boolean isNetworkAvailable() {
        if (AppUtils.getApp() == null) {
            return false;
        }
        try {
            ConnectivityManager connectivity = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivity != null) {
                NetworkInfo info = connectivity.getActiveNetworkInfo();
                return info.isAvailable();
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

    public static boolean isWiFi() {
        ConnectivityManager cm = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        // wifi的状态：ConnectivityManager.TYPE_WIFI
        // 3G的状态：ConnectivityManager.TYPE_MOBILE
        return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
    }

    //unchecked
    public static void openNetSetting(Activity act) {
        Intent intent = new Intent();
        ComponentName cm = new ComponentName("com.android.settings", "com.android.settings.WirelessSettings");
        intent.setComponent(cm);
        intent.setAction("android.intent.action.VIEW");
        act.startActivityForResult(intent, 0);
    }

    /**
     * 判断移动网络的类型
     *
     * @return 移动网络类型
     */
    private static String getNetworkClass() {
        TelephonyManager telephonyManager = (TelephonyManager) AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager == null) {
            return "未知";
        }
        @SuppressLint("MissingPermission")
        int networkType = telephonyManager.getNetworkType();
        switch (networkType) {
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return NETWORK_TYPE_2G;
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return NETWORK_TYPE_3G;
            case TelephonyManager.NETWORK_TYPE_LTE:
                return NETWORK_TYPE_4G;
            default:
                return "未知";
        }
    }

    /**
     * 判断 Wifi 是否启用
     */
    public static boolean isWifiEnabled() {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        return wifiManager.isWifiEnabled();
    }

    public static boolean isConnect2Wifi() {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        WifiInfo mWifiInfo = wifiManager.getConnectionInfo();
        Logger.e("mWifiInfo=" + mWifiInfo.toString());
        return mWifiInfo.getSupplicantState() == SupplicantState.COMPLETED;
    }


    public static boolean isWiFiActive() {
        Context context = AppUtils.getApp().getApplicationContext().getApplicationContext();
        ConnectivityManager connectivity = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++) {
                    if (info[i].getTypeName().equals("WIFI") && info[i].isConnected()) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * wifi是否连接
     *
     * @return
     */
    public static boolean isWifiConnected() {
        ConnectivityManager connManager = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo mWifiInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        return mWifiInfo.isConnected();
    }

    public static boolean setWifiEnabled(boolean enabled) {
        LogUtils.i("当前操作【" + (enabled ? "打开" : "关闭") + "WIFI】");
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        return wifiManager.setWifiEnabled(enabled);
    }

    public static void setDataEnabled(boolean enabled) {
        ConnectivityManager conMgr = (ConnectivityManager) AppUtils.getApp().getSystemService(Context.CONNECTIVITY_SERVICE);
        Class<?> conMgrClass = null;
        Field iConMgrField = null;
        Object iConMgr = null;
        Class<?> iConMgrClass = null;
        Method setMobileDataEnabledMethod = null;
        try {
            conMgrClass = Class.forName(conMgr.getClass().getName());
            iConMgrField = conMgrClass.getDeclaredField("mService");
            iConMgrField.setAccessible(true);
            iConMgr = iConMgrField.get(conMgr);
            iConMgrClass = Class.forName(iConMgr.getClass().getName());
            setMobileDataEnabledMethod = iConMgrClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
            setMobileDataEnabledMethod.setAccessible(true);
            setMobileDataEnabledMethod.invoke(iConMgr, enabled);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<ScanResult> getWifiScanResults() {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        return wifiManager.startScan() ? wifiManager.getScanResults() : null;
    }

    public static ScanResult getScanResultsByBSSID(String bssid) {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        ScanResult scanResult = null;
        boolean f = wifiManager.startScan();
        if (!f) {
            getScanResultsByBSSID(bssid);
        }
        List<ScanResult> list = wifiManager.getScanResults();
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                scanResult = list.get(i);
                if (scanResult.BSSID.equals(bssid)) {
                    break;
                }
            }
        }

        return scanResult;
    }

    public static WifiInfo getWifiConnectionInfo() {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        return wifiManager.getConnectionInfo();
    }

    public static boolean isNetworkOnline() {
        Runtime runtime = Runtime.getRuntime();
        try {
            Process ipProcess = runtime.exec("ping -c 3 mimo-iot-mqtt-staging.maxcares.com");
            int exitValue = ipProcess.waitFor();
            Logger.e("Avalible", "Process:" + exitValue);
            return (exitValue == 0);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return false;

    }


    /**
     * @return
     * @category 判断是否有外网连接（普通方法不能判断外网的网络是否连接，比如连接上局域网）
     */
    public static boolean ping(String... ips) {
        String ip;
        if (ips != null && ips.length > 0) {
            if (StringUtils.isEmpty(ips[0])) {
                ip = "www.baidu.com";
            } else {
                ip = ips[0];
            }
        } else {
            ip = "www.baidu.com";
        }

        String result = null;
        try {
            Process p = Runtime.getRuntime().exec("ping -c 3 -w 5 " + ip);// ping网址3次
            // 读取ping的内容，可以不加
            InputStream input = p.getInputStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(input));
            StringBuffer stringBuffer = new StringBuffer("");
            String content = "";
            while ((content = in.readLine()) != null) {
                stringBuffer.append(content);
            }
            Log.i("Ping", "------ping----- result content : " + stringBuffer.toString());
            // ping的状态
            int status = p.waitFor();
            if (status == 0) {
                result = "success";
                return true;
            } else {
                result = "failed";
            }
        } catch (IOException e) {
            result = "IOException";
        } catch (InterruptedException e) {
            result = "InterruptedException";
        } finally {
            Log.i("Ping", "----result---result = " + result);
        }
        return false;
    }

    /* *
     * @category 判断是否能与mqtt服务器连接，向mqtt服务器发送socket请求看是否有响应
     * @return
     */
    public static boolean socketTest(String host, int port) {
        String res = null;
        Socket socket = null;
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(host, port), 5000);
            LogUtils.d("socket connected");
            //向服务器发送消息
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            out.write("client sent --- PING ---");
            LogUtils.d("client sent --- PING ---");
            out.flush();// 刷新输出流，使Server马上收到该字符串

            //从服务器获取返回消息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            res = br.readLine();
            LogUtils.d("client get  server message : " + res);
            br.close();
            /*
            DataInputStream input = new DataInputStream(socket.getInputStream());
            res = input.readUTF();
            Log.i("Ping MQTT", "server 返回信息：" + res);*/
        } catch (Exception unknownHost) {
            LogUtils.e("You are trying to connect to an unknown host[" + host + "]!");
            return false;
        } finally {
            // 4: Closing connection
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 设置手表保存的wifi
     */
    public static void saveNetwork(String ssid, String pwd) {
        WifiManager wifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager != null) {
            WifiConfiguration wifiConfig = createWifiInfo(ssid, pwd, WifiCipherType.WIFICIPHER_WPA);
            if (wifiConfig == null) {
                LogUtils.w("wifiConfig is null!");
                return;
            }
            WifiConfiguration tempConfig = isExsits(wifiManager, ssid);
            if (tempConfig != null) {
                boolean result = wifiManager.removeNetwork(tempConfig.networkId);
                LogUtils.i("remove exsit network status result=" + result);
            }
            int netID = wifiManager.addNetwork(wifiConfig);
            LogUtils.i("add network " + netID);
            if (netID != -1) {
                //其中boolean参数，主要用于指定是否需要断开其它Wifi网络
                boolean result = wifiManager.enableNetwork(netID, false);
                LogUtils.i("save network status result=" + result);
            }
            wifiManager.saveConfiguration();
        }
    }

    private static WifiConfiguration createWifiInfo(String ssid, String password, WifiCipherType cipherType) {
        WifiConfiguration config = new WifiConfiguration();
        config.hiddenSSID = false;
        config.SSID = "\"".concat(ssid).concat("\"");
        config.status = WifiConfiguration.Status.ENABLED;

        if (cipherType == WifiCipherType.WIFICIPHER_WPA) {
            config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            config.preSharedKey = "\"".concat(password).concat("\"");
        } else if (cipherType == WifiCipherType.WIFICIPHER_WEP) {
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            if (!TextUtils.isEmpty(password)) {
                if (isHexWepKey(password)) {
                    config.wepKeys[0] = password;
                } else {
                    config.wepKeys[0] = "\"".concat(password).concat("\"");
                }
            }
            config.wepTxKeyIndex = 0;
        } else {
            config.preSharedKey = null;
            config.wepKeys[0] = "\"" + "\"";
            config.wepTxKeyIndex = 0;
            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            config.allowedAuthAlgorithms.clear();
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        }
        return config;
    }

    private static boolean isHexWepKey(String wepKey) {
        final int len = wepKey.length();
        // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
        if (len != 10 && len != 26 && len != 58) {
            return false;
        }
        return isHex(wepKey);
    }

    private static boolean isHex(String key) {
        for (int i = key.length() - 1; i >= 0; i--) {
            final char c = key.charAt(i);
            if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) {
                return false;
            }
        }
        return true;
    }

    /**
     * 查看以前是否也配置过这个网络
     */
    private static WifiConfiguration isExsits(WifiManager wifiManager, String ssid) {
        @SuppressLint("MissingPermission")
        List<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();
        if (existingConfigs != null && !existingConfigs.isEmpty()) {
            for (WifiConfiguration existingConfig : existingConfigs) {
                if (existingConfig.SSID.equals("\"" + ssid + "\"")) {
                    return existingConfig;
                }
            }
        }
        return null;
    }

    public static String getSimCardNo() {
        if(hasSimCard()){
            TelephonyManager telephonyManager = (TelephonyManager) AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE);
            return telephonyManager.getSimSerialNumber();
        }
        return "";
    }

    public static String getPhoneNumber() {
        if(hasSimCard()){
            TelephonyManager telephonyManager = (TelephonyManager) AppUtils.getApp().getSystemService(Context.TELEPHONY_SERVICE);
            return telephonyManager.getLine1Number();
        }
        return "";
    }

    /**
     * 获取wifi信号等级
     * @return
     */
    public static int getWifiRSSI() {
        if (NetUtils.isWifiConnected()) {
            WifiManager    mWifiManager = (WifiManager) AppUtils.getApp().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();
            return mWifiInfo.getRssi();
        }
        return -999;
    }

    private enum WifiCipherType {
        /**
         * 定义几种加密方式，一种是WEP，一种是WPA，还有没有密码的情况
         */
        WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
    }
}
